/*
 * Copyright (C) 2017-2018 Alibaba Group Holding Limited. All Rights Reserved.
 *
 *
 * Licensed under the Apache License, Version 2.0 (the License);
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#ifndef ALIOS_SPEECH_ASR_H_
#define ALIOS_SPEECH_ASR_H_

#include <stdint.h>
#include <string>
#include <memory>

/**
 * @file speech_asr.h
 * @brief This file contains ASRLocalEngine/ASRCloudEngine public interface defined by AliOS,
 * and is shared by the platform independent voice framework and the vendor specific Implementation.
 **/

namespace alios {

typedef enum {
  ASROk = 0,
  // common function error code.
  ASRFuncErrorInput = 2,
  ASRAllocateFailed = 3,
  ASRLocalEngineNotExist = 4,
  ASRInvalidState = 5,

  // file related error code.
  ASRFileNotFound = 10,
  ASRFileOpenFailed = 11,
  ASRFileJsonInvalidFormat = 12,

  // SR related error code.
  ASRSrInitializeFailed = 20,
  ASRSrNotExist = 21,
  ASRSrProcessFailed = 22,
  ASRSrNotInitialized = 23,
  ASRSrStartFailed = 24,
  ASRSrStopFailed = 25,
  ASRSrInvalidState = 26,
  ASRSrRescoreFailed = 27,

  // VAD related error code.
  ASRVadInitializeFailed = 30,
  ASRVadNotExist = 31,
  ASRVadProcessFailed = 32,
  ASRVadNotInitialized = 33,
  ASRVadStartFailed = 34,
  ASRVadStopFailed = 35,

  // AEC related error code.
  ASRAecInitializeFailed = 40,
  ASRAecNotExist = 41,
  ASRAecProcessFailed = 42,
  ASRAecNotInitialized = 43,

  // KWS related error code.
  ASRKwsInitializeFailed = 50,
  ASRKwsNotExist = 51,
  ASRKwsProcessFailed = 52,
  ASRKwsNotInitialized = 53,
  ASRKwsStartFailed = 54,
  ASRKwsStopFailed = 55,

  // Opus related error code.
  ASREncodeInitializeFailed = 60,
  ASREncodeNotExist = 61,
  ASREncodeProcessFailed = 62,
  ASREncodeNotInitialized = 63,

  // grammar related error code.
  ASRGrammarCreateFailed = 70,
  ASRGrammarInitializeFailed = 71,
  ASRGrammarCompileFailed = 72,
  ASRGrammarNotExist = 73,
  ASRGrammarUnitializeFailed = 74,

  // SV related error code.
  ASRSvCreateFailed = 80,
  ASRSvInitializeFailed = 81,
  ASRSvNotExist = 82,
  ASRSvStartRegisterFailed = 83,
  ASRSvRegisterFailed = 84,
  ASRSvStopRegisterFailed = 85,
  ASRSvStartLoginFailed = 86,
  ASRSvLoginFailed = 87,
  ASRSvStopLoginFailed = 88,
  ASRSvInvalidState = 89,

  // AEC_BEAMFORMER related error code.
  ASRAecBeamformerInitializeFailed = 100,
  ASRAecBeamformerNotExist = 101,
  ASRAecBeamformerProcessFailed = 102,
  ASRAecBeamformerNotInitialized = 103,

  ASRFuncNoSupport = 120,
  ASRUnknownError = 121,
} ASRRetCode;

typedef enum {
  ASRMandarin = 0,  // using Mandarin
  ASRCantonese = 1,  // using Cantonese
} ASRLanguageType;

typedef enum {
  ASRJSGF = 0,  // using jsgf
  ASRXBNF = 1,  // using xbnf
} ASRGrammarType;

typedef enum  {
  // sample rate = 8k, sample size = 16bits, channel num = 1.
  ASR8K16BitMono = 0,
  // sample rate = 16k, sample size = 16bits, channel num = 1.
  ASR16K16BitMono = 1,
  // sample rate = 16k, sample size = 16bits, channel num = 2,
  // channel 1 for reference, channel 2 for microphone.
  ASR16K16BitStereo_1Ref_2Mic = 2,
  // channel 1 for microphone, channel 2 for reference.
  ASR16K16BitStereo_1Mic_2Ref = 3,
  // sample rate = 16k, bits_sample = 16, channel_num = 4
  // channel 1 and 2 is for microphone, channel 3 and 4 is for reference.
  ASR16K16BitStereo_12Mic_34Ref = 4,
  ASR16K16BitStereo_4Mic = 5,
  // 1-6 speech channel and 7-8 are the reference channel
  ASR16K16BitStereo_1To6Mic_78Ref = 6,
  ASR16K32BitStereo_1To6Mic_78Ref = 7,
} ASRAudioFormat;

typedef enum {
  ASROpus = 0,
  ASROpusOgg = 1,
  ASRWav = 2,
} ASREncoder;

typedef enum {
  ASRNone = -1, // default none mode.
  ASRAuto = 0,  // using automatic voice activity detection.
  ASRPush2Talk = 1,  // using push to talk, i.e., without vad.
  ASRKws = 2,  // using key word spotting, then turn to auto mode.
  ASRKws2Talk = 3,  // using key word spotting, then turn to push2talk mode.
} ASRVadMode ;

typedef enum {
  ASRNoDebug = 0,  // without debug information.
  ASRLogSave = 1,  // save the log information into log.txt.
  ASRWaveSave = 2,  // save the audio data during the processing.
} ASRDebugMode;

typedef enum {
  ASRLogLevelError = 0,
  ASRLogLevelWarning = 1,
  ASRLogLevelInfo = 2,
  ASRLogLevelVerbose = 3,
} ASRLogLevel;

typedef enum {
  ASRWakeupKeywordWav,
  ASRActionKeywordWav,
  ASRPrefixKeywordWav,
  ASRSrWav,
} ASRDebugWavType;

typedef enum {
  ASRNothing = 0,
  ASRPartialResult = 1,
  ASRFinalResult = 2,
  ASRUserCancel = 3,
  ASRError = 4,
} ASRResultState;

typedef enum {
  ASRInvalidKeyword = -1,
  ASRWakeupKeyword = 0,
  ASRActionKeyword = 1,
  ASRPrefixKeyword = 2,
} ASRKeywordType;

typedef enum {
  ASRKeywordRejected = -1,
  ASRKeywordTrusted = 0,
  ASRKeywordNeedDoubleCheck = 1,
} ASRKeywordCredibility;

typedef enum {
  ASRGenderUnknown = -1,
  ASRGenderFemale = 0,
  ASRGenderMale = 1,
} ASRGenderType;

typedef enum {
  ASRSuccess = 0,
  ASRDefaultError = 1,
  ASRServerNullError = 2,
  ASRConnectionTimeout = 3,
  ASRNetworkInterruptted = 4,
  ASRNetworkClosed = 5,
  ASRLocalServiceNotReady = 6,
  ASRNoLocation = 7,
  ASRSrNetworkErr = 8,
  ASRSrError = 9,
  ASRSrNothing = 10,
  ASRSrNoResult = 11,
  ASRLocalNullResult = 12,
  ASRSrErrOffline = 13,
  ASRUnknown = 14,
  ASRSrErrSslInvalidCertificate = 15,
  ASRCloudUnsupport = 16,
  ASRAskAgain = 17,
  ASRAudioCaptureFailure = 18,
} ASRErrorCode;

typedef enum {
  ASRInvalidZone = 0,
  ASRFrontLeftZone = 1,
  ASRFrontRightZone = 2,
  ASRMiddleLeftZone = 4,
  ASRMiddleRightZone = 8,
  ASRBackLeftZone = 16,
  ASRBackRightZone = 32,
  ASRLeftZone = ASRFrontLeftZone | ASRMiddleLeftZone | ASRBackLeftZone,
  ASRRightZone = ASRFrontRightZone | ASRMiddleRightZone | ASRBackRightZone,
  ASRWholeZone = ASRLeftZone | ASRRightZone
} ASRVoiceZone;

class ASRKwsResult {
public:
  ASRKeywordType keyword_type;
  ASRKeywordCredibility keyword_credibility;
  std::string key_word;
  int kws_doa;
  ASRVoiceZone kws_vz;
  float confidence;
  ASRGenderType gender_type;
  int channel_id;
  float channel_snr;

  ASRKwsResult(): keyword_type(ASRInvalidKeyword),
    keyword_credibility(ASRKeywordRejected),
    key_word(""),
    kws_doa(0),
    kws_vz(ASRInvalidZone),
    confidence(0.f),
    gender_type(ASRGenderUnknown),
    channel_id(-1),
    channel_snr(0.f)
  {}
};

class ASRLocalEngineListener {
public:
  ASRLocalEngineListener() {}
  virtual ~ASRLocalEngineListener() {}
  /**
   * @brief notify ASRLocalEngineListener recoginition result
   * when ASRLocalEngine have recoginition result
   * @param[in] result string of recoginition
   * @param[result_state] state for result of recoginition
   * ASRSrNullResultForTimeout for null result with timeout
   * ASRSrPartialResult for partial result
   * ASRSrFinalResult for final result
   * result string streamed with json format, for example:
   * '{"results":[{"nbest":[{"confidence":37.737178802490234,//本地识别打分，仲裁需要，超过阈值
   * "raw_confidence":-4.7886042594909668, // 原生打分，仲裁需要
   * "text":"打开", //识别结果文字 "words": // 建议提供，其中包括发音
   * [{"confidence":54.609428405761719,"end_time":17,"pronunciation":"da3",
   * "raw_confidence":-4.0960578918457031,"start_time":12,"word":"打"},
   * {"confidence":82.260780334472656,"end_time":21,"pronunciation":"kai1",
   * "raw_confidence":-2.73321533203125,"start_time":18,"word":"开"}]}],"source":"jsgf"
   * //识别结果来源，需要指定}],"version":"aispeech1.0",//本地识别引擎版本
   * "state":"final" // 识别结果状态，最终结果或者中间结果temporary}'
   */
  virtual void OnRecognitionResult(const char *result,
                                   ASRResultState result_state) = 0;

  /**
   * @brief notify ASRLocalEngineListener begin having voice data
   * when ASRLocalEngine receive user input useful voice data,
   * which except vad and noise data.
   */
  virtual void OnVoiceStart(bool enableOneShot = false, const std::string& keyword = std::string("")) = 0;

  /**
   * @brief notify ASRLocalEngineListener opus data
   * when ASRLocalEngine receive user input useful voice data
   * @param[encoder] ASR encoder
   * @param[data] binary voice data encoded with ogg/opus format
   * @param[length] voice data length
   */
  virtual void OnVoiceData(const ASREncoder encoder, const char *data, int length) = 0;

  /**
   * @brief notify ASRLocalEngineListener end of receiving voice data
   * when ASRLocalEngine finish voice data which except vad and noise data.
   * @param[quiet] whether report voice end message to client
   */
  virtual void OnVoiceEnd(bool quiet = false) = 0;

  /**
   * @brief notify ASRLocalEngineListener begin processing keyword
   * when ASRLocalEngine begin process keyword
   * @param[keyword_info] which keyword
   */
  virtual void OnKeywordStart(const std::string &keyword_info) = 0;

  /**
   * @brief notify ASRLocalEngineListener keyword audio opus data
   * when ASRLocalEngine process keyword
   * @param[encoder] ASR encoder
   * @param[data] binary voice data encoded with ogg/opus format
   * @param[length] voice data length
   */
  virtual void OnKeywordData(const ASREncoder encoder, const unsigned char *data, int length) = 0;

  /**
   * @brief notify ASRLocalEngineListener end of receiving keyword voice data
   * when ASRLocalEngine finish keyword voice data.
   */
  virtual void OnKeywordEnd() = 0;

  /**
   * @brief notify ASRLocalEngineListener keyword spot
   * when ASRLocalEngine spot one keyword
   * @param[kws_result] spotted keyword result
   */
  virtual void OnKeywordSpotted(const ASRKwsResult &kws_result) = 0;

  /**
   * @brief notify ASRLocalEngineListener ASRLocalEngine cancel asr process
   * when ASRLocalEngine is called by Cancel.
   */
  virtual void OnCancelled() = 0;
};

class ASRLocalEngine {
public:
  ASRLocalEngine() {}
  virtual ~ASRLocalEngine() {}

  /**
   *   @brief return version of ASRLocalEngine.
   *   @return asr engine version
   */
  virtual const char *GetVersion() const = 0;

  /**
   * @brief set ASRLocalEngineListener listener to ASRLocalEngine for notify info from ASRLocalEngine
   * @param[listener] for receive notify from ASRLocalEngine
   * listener can be null or one customed object of subclass ASRLocalEngineListener.
   */
  virtual void SetListener(ASRLocalEngineListener *listener) = 0;

  /**
   * @brief get ASRLocalEngine keywords params
   * @return for keywords used in ASRLocalEngine
   * its content is json format, for example:
   * '{"word_list":[{"name":"你好小","type":"wakeup","activation":true,"is_main":true}]}'
   */
  virtual const char *GetKeywordsParams() const = 0;

  /**
   * @brief set keywords params to ASRLocalEngine
   * @return result of set keywords
   * @param[keywords_params] keywords to ASRLocalEngine
   * its content is json format, for example:
   * '{"keyword_list":[{"keyword":0, "enabled":true}]}'
   */
  virtual ASRRetCode SetKeywordsParams(const char *keywords_params) = 0;

  /**
   * @brief set wakeup keywords params to WakeupEngine
   * @return result of set keywords
   * @param[keywords_params] keywords to WakeupEngine
   * its content is json format, for example:
   * '{"word_list":[{"name":"你好小张"},{"name":"你好小明"}]}'
   * @return[retcode] return WakeupEngine result for set wakeup keywords.
   */
   virtual ASRRetCode SetWakeupKeywordsParams(const char *keywords_params) = 0;

  /**
   * @brief set custom keywords to ASRLocalEngine
   * @param[custom_keywords] custom keywords ASRLocalEngine will use
   * custom_keywords string is json format, for example:
   * '{"word_list":[{"name":"上一个"},{"name":"下一个"},{"name":"取消收藏"}]}'
   * @return[retcode] return ASRLocalEngine result for set custom keywords.
   */
  virtual ASRRetCode SetCustomizedKeywords(const char *custom_keywords) = 0;

  /**
   * @brief set vad mode to ASRLocalEngine
   * @param[vad_mode] recognition vad mode ASRLocalEngine will use
   * vad_mode can be AAuto/APush2Talk/AKws/AKws2Talk
   * ASRLocalEngine can support optional modes.
   */
  virtual ASRRetCode SetVadMode(ASRVadMode vad_mode) = 0;

  /**
   * @brief return vad mode of ASRLocalEngine
   * return asr engine vad mode, can be AAuto/APush2Talk/AKws/AKws2Talk
   */
  virtual ASRVadMode GetVadMode() { return alios::ASRNone; };

  /**
   * @brief set vad front time for timeout to ASRLocalEngine
   * @param[time] time(ms) timeout for vad front with milliseconds
   * @return[retcode] return ASRLocalEngine support status.
   */
  virtual ASRRetCode SetVadFrontTimeoutInterval(int32_t time) = 0;

  /**
   * @brief set audio format to ASRLocalEngine which audio format data
   * @param[audio_foramt] ASRLocalEngine will receive this format audio data.
   * @return[retcode] return ASRLocalEngine support status.
   */
  virtual ASRRetCode SetAudioFormat(ASRAudioFormat audio_format) = 0;

  /**
   * @brief set active angle to ASRLocalEngine
   * @param[active_angle] active angle for ASRLocalEngine will use
   * @return[retcode] return ASRLocalEngine support status.
   */
  virtual ASRRetCode SetActiveAngle(int active_angle) { return alios::ASRFuncNoSupport; }

  /**
   * @brief set voice zone to ASRLocalEngine
   * @param[active_zone] voice zone for ASRLocalEngine will use
   * @return[retcode] return ASRLocalEngine support status.
   */
  virtual ASRRetCode SetActiveZone(ASRVoiceZone active_zone) { return alios::ASRFuncNoSupport; }

  // initialize the asr, vad, and opus engines.
  /**
   * @brief initialize ASRLocalEngine
   * @param[assets_path] assets path for ASRLocalEngine will acces resources
   * @param[save_path] for ASRLocalEngine can save tmp data path
   * @param[cust_conf] the customized resource(cfg, asp, kws...) file/folder names for different models,
   * it's json string, e.g. "{"asp":"xxx.modelY", "cfg":"xxx.modelZ"}"
   * @param[lang_type] for ASRLocalEngine recognition lang
   * @return[retcode] return ASRLocalEngine result for Initialize.
   */
  virtual ASRRetCode Initialize(const std::string &assets_path,
                    const std::string &save_path = "",
                    const std::string &cust_conf = "",
                    ASRLanguageType lang_type = ASRMandarin) = 0;

  /**
   * @brief uninitialize to ASRLocalEngine
   */
  virtual ASRRetCode Uninitialize() = 0;

  /**
   * @brief set grammar content and its tag to ASRLocalEngine
   * @param[grammar_tag] grammar tag for grammars ASRLocalEngine will use
   * @param[grammar_content] grammar content ASRLocalEngine will use
   * its contents are jsgf format
   * @param[is_overwrite] ASRLocalEngine will overwrite its previous grammars or not
   * @param[is_immediatly_active] ASRLocalEngine active new grammar or not
   * @param[lang_type] set ASRLocalEngine new grammar lang
   * @param[grammar_type] set ASRLocalEngine new grammar type lang
   * @return[retcode] return ASRLocalEngine result for CompileGrammar.
   */
  virtual ASRRetCode CompileGrammar(const std::string &grammar_tag,
                        const std::string &grammar_content,
                        const std::string &vocab_content,
                        bool is_overwrite, bool is_immediatly_active = false,
                        ASRLanguageType lang_type = ASRMandarin,
                        ASRGrammarType grammar_type = ASRJSGF) = 0;

  /**
   * @brief set ASRLocalEngine start audio recognition
   * @param[grammar_tag] grammar tag for grammars ASRLocalEngine will use
   * @param[is_need_result] set ASRLocalEngine will notify asr result or not
   * @return[retcode] return ASRLocalEngine result for Start.
   * if Start successfully, voice service will send audio data to ASRLocalEngine
   */
  virtual ASRRetCode Start(const std::string &grammar_tag, bool is_need_result) = 0;

  /**
   * @brief set ASRLocalEngine start asr recognition, preset mode should be KWS
   * @return[retcode] return ASRLocalEngine result for StartAsr.
   * if StartAsr successfully, ASRLocalEngine will start asr recognition
   */
  virtual ASRRetCode StartAsr() { return alios::ASRFuncNoSupport; };

  /**
   * @brief set ASRLocalEngine stop audio recognition
   * when ASRLocalEngine stop, ASRLocalEngine should notify ASRLocalEngineListener.
   * @return[retcode] return ASRLocalEngine result for Stop.
   */
  virtual ASRRetCode Stop() = 0;

  /**
   * @brief set ASRLocalEngine cancel audio recognition
   * when ASRLocalEngine finish cancel, ASRLocalEngine should notify ASRLocalEngineListener OnCancelled.
   * @return[retcode] return ASRLocalEngine result for Cancel.
   */
  virtual ASRRetCode Cancel() = 0;

  /**
   * @brief set ASRLocalEngine cancel asr recognition
   * @return[retcode] return ASRLocalEngine result for CancelAsr.
   * if CancelAsr successfully, ASRLocalEngine will stop asr recognition
   */
  virtual ASRRetCode CancelAsr() { return alios::ASRFuncNoSupport; };

  /**
   * @brief Send Audio Data to ASRLocalEngine
   * @param[wav_data] audio pcm data with audio format.
   * @param[sample_num] wav_data contains sample number.
   * @return[retcode] return ASRLocalEngine result for UpdateAudioData.
   */
  virtual ASRRetCode UpdateAudioData(const int16_t *wav_data, int32_t sample_num) = 0;

  /**
   * @brief rescore nlu result with ASRLocalEngine
   * @param[nlu_result_json] nlu_result_json should rescored with ASRLocalEngine
   * @param[rescored_slot_json] rescore result for nlu_result_json
   * @return[retcode] return ASRLocalEngine result for RescoreResult.
   */
  virtual ASRRetCode RescoreResult(const std::string &nlu_result_json,
                       std::string &rescored_slot_json) { return alios::ASRFuncNoSupport; }

  // for debug interface
  /**
   * @brief set log level to ASRLocalEngine
   * @param[log_level] log level ASRLocalEngine will use
   * note only for debug.
   */
  virtual void SetLogLevel(ASRLogLevel log_level) {}

  /**
   * @brief set debug mode to ASRLocalEngine
   * @param[debug_mode] recoginition ASRLocalEngine will use
   * @param[save_path] save audio data path ASRLocalEngine will use
   * note only for debug.
   */
  virtual void SetDebugMode(ASRDebugMode debug_mode, const std::string &save_path) {}
};

class ASRCloudEngineListener {
public:
  ASRCloudEngineListener() {}
  virtual ~ASRCloudEngineListener() {}

public:
  /**
   * @brief notify ASRCloudEngineListener recoginition result
   * when ASRCloudEngine have recoginition result
   * @param[in] result string of recoginition
   * @param[result_state] state for result of recoginition
   * ASRSrNullResultForTimeout for null result with timeout
   * ASRSrPartialResult for partial result
   * ASRSrFinalResult for final result
   * result string streamed with json format, for example:
   * '{"results":{"asr_out":{ // asr识别结果输出
   * "duration":1787, // 语音时间长度单位ms "result":"打开", // 识别结果
   * "uid":"f428057fefad851f4b7555762f76848d",
   * // 唯一id，框架会在调用ASRCloudEngine StartVoice之前，通过调用SetQueryId来设置
   * "confidence":1.0, // 识别打分,预留未来参与仲裁 "finish":1, // 已完成, 0 表示中间结果
   * "version":"4.0", // 云端asr识别版本
   * "pronunciation":"da3 kai2", // 识别结果发音
   * "status":1 // 识别状态，内部保留字段，可不支持}}}'
   */
  virtual void OnASRResult(const char *result, ASRResultState result_state) {}

  /**
   * @brief notify ASRCloudEngineListener recoginition result error
   * when ASRCloudEngine have recoginition result error.
   * @param[result_state] state for result of recoginition
   * @param[error] for error reason code
   */
  virtual void OnASRError(ASRResultState result_state, ASRErrorCode error) {}
};

class ASRCloudEngine {
public:
  ASRCloudEngine() {}
  virtual ~ASRCloudEngine() {}
public:
  /**
   * @brief SetQueryId to ASRCloudEngine for identify asr session queryid.
   * @param[query_id] uuid for ASRCloudEngine identify asr process id
   * its content should be contained in asr result value with uid key.
   */
  virtual void SetQueryId(std::string query_id) = 0;

  /**
   * @brief GetQueryId of ASRCloudEngine for identify session queryid.
   * @return queryid which ASRCloudEngine is used.
   * its content should be contained in asr result value with uid key.
   */
  virtual std::string GetQueryId() = 0;
  /**
   * @brief SetVocabulary for ASRCloudEngine
   * @return
   * @param[vocabulary] vocabulary for ASRCloudEngine
   * its content is json format {"word":weight} ,
   * weight 1-5
   * for example:
   * {"关羽":5,"张飞":5,"赵云":5}
   * it must be enabled when next calls for startVoice
   */
  virtual void SetVocabulary(std::string &vocabulary) = 0;

  /**
   * @brief update wakeup words for  ASRCloudEngine
   * @return
   * @param words for ASRCloudEngine
   */
  virtual void SetWakeupWords(std::string words) = 0;

  /**
   * @brief set asr listener for  ASRCloudEngine
   * @return
   * @param[listener] listener for ASRCloudEngine
   */
  virtual void SetListener(ASRCloudEngineListener *listener) = 0;

  /**
   * @brief called when start begin, to connect, build and send protocal header etc.
   * @return
   * @param[isDictation] isDictation
   */
  virtual void Start(bool is_dictation) = 0;

  /**
   * @brief called when voice data reach
   * @return
   * @param[encoder] encoder
   * @param[data] data
   * @param[length] length
   */
  virtual void UpdateVoiceData(const ASREncoder encoder, const char *data, const int length) = 0;

  /**
   * @brief called when voice end,to tell the server stop.
   * @return
   */
  virtual void Stop() = 0;

  /**
   * @brief to cancle this session of asr .
   * @return
   */
  virtual void Cancel() = 0;
};

}  // namespace alios

#if __GNUC__ >= 4
#  define ASR_EXPORT_API __attribute__ ((visibility ("default")))
#  define ASR_IMPORT_API __attribute__ ((visibility ("default")))
#  define ASR_INTERNAL   __attribute__ ((visibility ("hidden")))
#else
/** Visibility attribute to show method definitions */
#  define ASR_EXPORT_API
/** Visibility attribute to show declarations */
#  define ASR_IMPORT_API
/** Visibility attribute to hide declarations */
#  define ASR_INTERNAL
#endif

#define ASR_CREATELOCALENGINE_SYM "ASR_CreateLocalEngine"
#define ASR_DESTROYLOCALENGINE_SYM "ASR_DestroyLocalEngine"
#define ASR_CREATECLOUDENGINE_SYM "ASR_CreateCloudEngine"
#define ASR_DESTROYCLOUDENGINE_SYM "ASR_DestroyCloudEngine"

/*----------------------------------------------------------------------*/
/*                        Function Prototypes                           */
/*----------------------------------------------------------------------*/
#ifdef __cplusplus
extern "C" {
#endif

//
// ASR Engine library default entry points.
// ASR_CreateLocalEngine/ASR_DestroyLocalEngine.
// ASR_CreateCloudEngine/ASR_DestroyCloudEngine.
//
typedef alios::ASRLocalEngine* (*ASR_CreateLocalEngineFunc)(void);
typedef alios::ASRRetCode (*ASR_DestroyLocalEngineFunc)(alios::ASRLocalEngine* engine);
typedef alios::ASRCloudEngine* (*ASR_CreateCloudEngineFunc)(void);
typedef alios::ASRRetCode (*ASR_DestroyCloudEngineFunc)(alios::ASRCloudEngine* engine);

#ifdef __cplusplus
}  /* end extern "C" */
#endif

#endif  // ALIOS_SPEECH_ASR_H_
